#ifndef _INI_INFO_H_
#define _INI_INFO_H_

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <limits>
#include <exception>
#include <sstream>

#include "OptionType.h"
#include "OptionTypeBool.h"
#include "OptionTypeNumeric.h"
#include "OptionTypeString.h"
#include "OptionTypeEnum.h"


namespace inilib
{

	// ----------------------------------------------------------
	// Exceptions
	// ----------------------------------------------------------

	/**
	 * All the exceptions that occur in this library should be based on this class.
	 */
	class ExceptionIniLib
	{
	public:
		ExceptionIniLib ( const std::string & info )
		{
			m_Info = info;
		}

		std::string GetInfo () const
		{
			return m_Info;
		}

	private:
		std::string m_Info;
	};

	// ----------------------------------------------------------
	// IniInfo
	// ----------------------------------------------------------

	/**
	 * Format of ini file is mandatory when working with ini files, because it
	 * contains all the information about the structure. Without it we have no
	 * way of knowing how the ini file is suppose to look like and whether it is valid.
	 *
	 * It is created simply by adding sections and options. Section should be added before all
	 * its options.
	 *
	 * IniInfo is responsible for deallocating memory of all options that has been added.
	 */
	class IniInfo
	{
	public:

		friend class IniFile;

		explicit IniInfo ();
		~IniInfo ();

		/**
		 * Adds particular section. If there is already a section with given name, an exception
		 * will be thrown.
		 */
		void AddSection (
			const std::string & sectionName,
			Mandatory isMandatory = NONMANDATORY
		);
		
		/**
		 * Adds particular option to given section. It is necessary to add section before all the options
		 * otherwise it will cause exception.
		 */
		void AddOption (
			const std::string & sectionName,
			OptionType * option
		);

	private:

		// ----------------------------------------------------------
		// SectionInfo
		// ----------------------------------------------------------

		class SectionInfo
		{
		public:
			explicit SectionInfo ()
			{
			}

			explicit SectionInfo ( const std::string & name, bool isMandatory )
			{
				m_Name = name;
				m_IsMandatory = isMandatory;
			}

			bool m_IsMandatory;
			std::string m_Name;
			
			std::map< std::string, OptionType * > m_Options;
		};

		std::map< std::string, SectionInfo > m_Sections;
	};

}

#endif
